home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK2.toast / Development Kits / Zoomed Video Driver v1.0 SDK / Sample Driver / AcmeZVDrvr.c next >
Encoding:
C/C++ Source or Header  |  1997-06-02  |  25.5 KB  |  876 lines  |  [TEXT/CWIE]

  1.  
  2. /*/*************************************************************************
  3. **    PowerBook Software Group
  4. **
  5. **    PowerBook's Zoomed Video Driver Sample
  6. **
  7. **    by Philip Nguyen , (nguyen.p@apple.com)
  8. **    PowerBook Software Group
  9. **
  10. **     with help from Dave Falkenberg
  11. **
  12. **  " It works on my PowerBook! "
  13. **
  14. **    File:        ZVDrvr.c
  15. **
  16. **    Copyright © 1996 Apple Computer, Inc.
  17. **    All rights reserved.
  18. **
  19. **    You may incorporate this sample code into your applications without
  20. **    restriction, though the sample code has been provided "AS IS" and the
  21. **    responsibility for its operation is 100% yours.  However, what you are
  22. **    not permitted to do is to redistribute the source as "DSC Sample Code"
  23. **    after having made changes. If you're going to re-distribute the source,
  24. **    we require that you make it clear in the source that the code was
  25. **    descended from Apple Sample Code, but that you've made changes.
  26. **
  27. **************************************************************************/
  28.  
  29. #define BUILDING_FOR_SYSTEM7 1
  30.  
  31. #include <Devices.h>
  32. #include <DriverServices.h>
  33. #include <NameRegistry.h>
  34. #include <QuickTimeComponents.h>
  35. #include <Types.h>
  36.  
  37. #include "AcmeZVDrvr.h"
  38. #include "ZoomedVideo.h"
  39.  
  40.  
  41. //=====================================================================================================
  42. //
  43. // Forward declarations.
  44. //
  45. //=====================================================================================================
  46. OSStatus     DoDriverIO(AddressSpaceID addressSpaceID, IOCommandID ioCommandID, IOCommandContents ioCommandContents, IOCommandCode ioCommandCode, IOCommandKind ioCommandKind);
  47. static        OSStatus DoInitialization(SInt16 refNum, const RegEntryIDPtr regEntryID, Boolean replacingDriver);
  48. static        OSStatus DoFinalization(SInt16 refNum, const RegEntryIDPtr regEntryID, Boolean beingReplaced);
  49. static        OSStatus DoHardwareInit(Boolean open);
  50. static        OSStatus DoControl(CntrlParam *pb);
  51. static        OSStatus DoStatus(CntrlParam *pb);
  52. static        OSStatus GetZoomVideo(ZVFlagRecord *zvStatus);
  53. static        OSStatus DoZoomVideo(ZVFlagRecord *turnZVOn);
  54. static        OSStatus CheckInputCapabilities(UInt32 *inputFlag);
  55. static        OSStatus GetZVInfo(ZVInfo *myData);
  56. static        OSStatus DoAnalogControl(ZVAnalogControlRecord *analogData);
  57. static        OSStatus DoCheckVsync(ZVFlagRecord * vSync);
  58. static         OSStatus DoSetInputSource( UInt16 * inputSource);
  59. static         OSStatus DoSetInputStandard( UInt16 * inputStandard);
  60. static        UInt16      CheckVsyn(void);
  61. static        OSStatus DoGetAnalogDefaults( ZVAnalogControlRecord * myData);
  62. static         OSStatus DoGetNumberOfInputs( UInt16 *numberOfInputs );
  63. static         OSStatus DoGetInput( UInt16 *inputSource );
  64. static         OSStatus DoGetInputFormat( UInt16 *inputSource );
  65. static        OSStatus WriteSIOLoop(UInt16 data);
  66. static        void      WriteSIO(UInt16 byte);
  67. static        void      SIOSendByte(UInt8 SIOdata);
  68. static        void      SIORegWrite(UInt8 data);
  69. static        void      SIOStart(Boolean start);
  70. static        UInt8      AdjustSIOData(UInt8 data);
  71.  
  72.  
  73. //=====================================================================================================
  74. //
  75. // Globals
  76. //
  77. //=====================================================================================================
  78. volatile         ZVRegisters *gZVRegisters;
  79. RegEntryID        gRegEntryID;
  80. UInt8            gvalue;
  81. Boolean            gZVideoOn;
  82. UInt16            gSaturation;
  83. UInt16            gBrightness;
  84.  
  85.  
  86. //=====================================================================================================
  87. //
  88. // The DriverDescription
  89. //
  90. //=====================================================================================================
  91. #pragma mark TheDriverDescription
  92. enum
  93. {
  94.     kMajorRev = 1, 
  95.     kMinorAndBugRev = 1,
  96.     kStage = alphaStage,                                        // developStage, alphaStage, betaStage, finalStage
  97.     kNonRelRev = 1
  98. };
  99.  
  100. DriverDescription TheDriverDescription = {
  101.     kTheDescriptionSignature,                                    // Driver Desrciption Signature
  102.     kInitialDriverDescriptor,                                    // Driver Description Version
  103.  
  104.     // driverType
  105.     {
  106.         kZVNodeName,                                            // DeviceName (matches name registry node name)
  107.         kMajorRev, kMinorAndBugRev, kStage, kNonRelRev,            // Driver version
  108.     },
  109.     
  110.     // driverOSRuntimeInfo
  111.     {
  112.         kDriverIsLoadedUponDiscovery | kDriverIsOpenedUponLoad,    // Runtime Options
  113.         kZVDriverName,                                            // Unit Table Driver Name
  114.     },
  115.     
  116.     // driverSerives
  117.     1,                                                            // nServices
  118.     kServiceCategoryNdrvDriver,                                    // Service Category ('ndrv')
  119.     kNdrvTypeIsGeneric,                                            // Type withing category (generic)
  120.     1, 0, finalStage, 0                                            // Version of the DriverDescription format
  121. };
  122.  
  123.  
  124. //=====================================================================================================
  125. //
  126. // The DriverDescription
  127. //
  128. //=====================================================================================================
  129. #pragma mark -
  130. #pragma mark ••••• Standard Native Driver Functions •••••
  131.  
  132. OSStatus DoDriverIO(    AddressSpaceID        addressSpaceID,
  133.                         IOCommandID            ioCommandID,
  134.                         IOCommandContents    ioCommandContents,
  135.                         IOCommandCode        ioCommandCode,
  136.                         IOCommandKind        ioCommandKind)
  137. {
  138. #pragma unused (addressSpaceID)
  139.  
  140.     OSStatus    status = noErr;
  141.  
  142.     /*
  143.      * Note: Initialize, Open, KillIO, Close, and Finalize are either synchronous
  144.      * or immediate. Read, Write, Control, and Status may be immediate,
  145.      * synchronous, or asynchronous.
  146.      */
  147.     switch (ioCommandCode)
  148.         {
  149.         case kInitializeCommand:            /* Initialize                        */
  150.         case kReplaceCommand:                /* or replace an old driver            */
  151.  
  152.             status = DoInitialization(    ioCommandContents.initialInfo->refNum,
  153.                                         &ioCommandContents.initialInfo->deviceEntry,
  154.                                         (ioCommandCode == kReplaceCommand));
  155.             break;
  156.  
  157.         case kFinalizeCommand:                /* Finalize                            */
  158.         case kSupersededCommand:            /* or get ready to be replaced        */
  159.  
  160.             status = DoFinalization(    ioCommandContents.initialInfo->refNum,
  161.                                         &ioCommandContents.initialInfo->deviceEntry,
  162.                                         (ioCommandCode == kSupersededCommand));
  163.             break;
  164.  
  165.         case kOpenCommand:                    /* Open and Close don’t do anything */
  166.             status = DoHardwareInit(true);
  167.             break;
  168.  
  169.         case kCloseCommand:
  170.             status = DoHardwareInit(false);
  171.             break;
  172.  
  173.         case kControlCommand:
  174.             status = DoControl((CntrlParam *) ioCommandContents.pb);
  175.             break;
  176.  
  177.         case kStatusCommand:
  178.             status = DoStatus((CntrlParam *) ioCommandContents.pb);
  179.             break;
  180.  
  181.         case kReadCommand:
  182.         case kWriteCommand:
  183.         case kKillIOCommand:
  184.         default:
  185.             status = paramErr;
  186.             break;
  187.         }
  188.  
  189.     /*
  190.      * Force a valid result for immediate commands -- they must return a valid
  191.      * status to the Driver Manager: returning kIOBusyStatus would be a bug..
  192.      * Non-immediate commands return a status from the lower-level routine. If the
  193.      * status is kIOBusyStatus, we just return -- an asynchronous I/O completion
  194.      * routine will eventually complete the request. If it's some other status, the
  195.      * lower-level routine has completed a non-immediate task, so we call
  196.      * IOCommandIsComplete and return its (presumably noErr) status.
  197.      */
  198.     if ((ioCommandKind & kImmediateIOCommandKind) != 0)
  199.         {
  200.         /* Immediate commands return the operation status        */
  201.         }
  202.     else if (status == ioInProgress)
  203.         {
  204.         /*
  205.          * An asynchronous operation is in progress. The driver handler promises
  206.          * to call IOCommandIsComplete when the operation concludes.
  207.          */
  208.         status = noErr;
  209.         }
  210.     else
  211.         {
  212.         /*
  213.          * Normal command that completed synchronously. Dequeue the user's
  214.          * parameter block.
  215.          */
  216.         status = IOCommandIsComplete(ioCommandID, status);
  217.         }
  218.  
  219.     return status;
  220.     }
  221.  
  222.  
  223. //=====================================================================================================
  224. //
  225. //  DoInitialization
  226. //
  227. //        -> regEntryID    The NameRegistry ID for this device.
  228. //
  229. //        -> replacingDriver
  230. //        This indicates whether the driver is being initialized (replacingDriver == false) or replaced
  231. //        (replacingDriver == true).
  232. //        These commands are similar, but with subtle differences.  A 'initialize' command is issued
  233. //        if no version of this driver has been previously loaded, whereas a 'replace' is
  234. //        issued if a previous version of the driver has been loaded, but subsequently superseded.
  235. //
  236. //        This routine should initialize the hardware to a known state and initialize any globals.  If the
  237. //        regEntryID is needed later on, then one should make a copy and store it in the globals.
  238. //=====================================================================================================
  239. static OSStatus DoInitialization(SInt16 refNum, const RegEntryIDPtr regEntryID, Boolean replacingDriver)
  240. {
  241. #pragma unused (refNum,replacingDriver)
  242.  
  243.     OSStatus                status;
  244.     RegPropertyValueSize     propertySize;
  245.     
  246.     // Save the regEntryID,
  247.     RegistryEntryIDCopy(regEntryID, &gRegEntryID);
  248.  
  249.     // Look for our AAPL,address property, so we can get the base address of our card.
  250.     // First, see if it exists by attempting to get its size
  251.     status = RegistryPropertyGetSize(regEntryID,"AAPL,address",&propertySize);
  252.     if (status == noErr) 
  253.     {
  254.         status = RegistryPropertyGet( regEntryID, "AAPL,address", (RegPropertyValue *) &gZVRegisters,&propertySize);
  255.     }
  256.     
  257.     return status;
  258. }
  259.     
  260.  
  261. //=====================================================================================================
  262. //
  263. //  DoFinalization
  264. //
  265. //    This routine is called after getting a 'kFinalizeCommand' or 'kSupersededCommandin DoDriverIO().  
  266. //  A 'kFinalizeCommand' is issued if the driver is going away for good, and a 'kSupersededCommand' is 
  267. //  issued if the driver will be replaced with a later, greater version.
  268. //
  269. //  This routine should dispose of any data that was allocated in the initialize command.
  270. //=====================================================================================================
  271. static OSStatus DoFinalization(SInt16 refNum, const RegEntryIDPtr regEntryID, Boolean beingReplaced)
  272. {
  273. #pragma unused (refNum,regEntryID,beingReplaced)
  274.     
  275.     // Dispose of the regEntryID we created earlier.
  276.     RegistryEntryIDDispose(&gRegEntryID);
  277.  
  278.     return noErr;
  279. }
  280.  
  281.  
  282. #pragma mark -
  283. #pragma mark ••••• Driver Specific Calls •••••
  284. //=====================================================================================================
  285. //
  286. //  DoHardwareInit
  287. //
  288. //  Perform any necessary hardware initialization required, or if open == false, any termination 
  289. //  required.
  290. //
  291. //=====================================================================================================
  292. static OSStatus DoHardwareInit(Boolean    open)
  293. {
  294. #pragma unused (open)
  295.  
  296.     return noErr;
  297. }
  298.  
  299.  
  300. //=====================================================================================================
  301. //
  302. //  DoControl
  303. //
  304. //  Process a PBControl command.  This is the main entry point for ZV calls.
  305. //
  306. //=====================================================================================================
  307. static OSStatus DoControl(CntrlParam *pb)
  308. {
  309.     OSErr    status = controlErr;
  310.     void     * genericPtr;
  311.     
  312.     // The 'csParam' field of the 'CntrlParam' stucture is defined as 'short csParam[11]'.  This is
  313.     // meant for 'operation defined parameters.' For the AV driver, only the first 4 bytes are
  314.     // used.  They are used as a pointer to another structure.
  315.     // To help code readability, the pointer will be extracted as a generic 'void *' and then cast as
  316.     // appropriate.
  317.  
  318.     genericPtr = (void *) *((UInt32 *) &(pb->csParam[0]));
  319.     
  320.     switch (pb->csCode)
  321.     {
  322.         case    cscZVVideoEnable:
  323.             status = DoZoomVideo( (ZVFlagRecord *) genericPtr );
  324.             break;
  325.             
  326.         case    cscZVSetCurrentAnalogValue: // Analog controls
  327.             status = DoAnalogControl( (ZVAnalogControlRecord *) genericPtr );
  328.             break;
  329.  
  330.         case    cscZVSetInput: 
  331.             status = DoSetInputSource( (UInt16 *) genericPtr );
  332.             break;
  333.  
  334.         case    cscZVSetInputStandard: 
  335.             status = DoSetInputStandard( (UInt16 *) genericPtr );
  336.             break;
  337.  
  338.         default:                    /* Unknown csCode        */
  339.             status = controlErr;
  340.             break;
  341.         }
  342.  
  343.     return status;
  344. }
  345.     
  346. //=====================================================================================================
  347. //
  348. //  DoStatus
  349. //
  350. //  Process a PBStatus command.  This is the main entry point for ZV calls.
  351. //
  352. //=====================================================================================================
  353. static OSStatus DoStatus(CntrlParam *pb)
  354. {
  355.     OSErr    status = statusErr;
  356.     void     * genericPtr;
  357.     
  358.     // The 'csParam' field of the 'CntrlParam' stucture is defined as 'short csParam[11]'.  This is
  359.     // meant for 'operation defined parameters.' For the AV driver, only the first 4 bytes are
  360.     // used.  They are used as a pointer to another structure.
  361.     // To help code readability, the pointer will be extracted as a generic 'void *' and then cast as
  362.     // appropriate.
  363.  
  364.     genericPtr = (void *) *((UInt32 *) &(pb->csParam[0]));
  365.     
  366.     switch (pb->csCode)
  367.     {
  368.         case    cscZVGetVideoEnable:
  369.             status = GetZoomVideo( (ZVFlagRecord *) genericPtr );
  370.             break;
  371.  
  372.         case    cscZVGetDefaultAnalogValue:
  373.             status = DoGetAnalogDefaults( (ZVAnalogControlRecord *) genericPtr );
  374.             break;
  375.  
  376.         case    cscZVGetVSyncState: // check for Vsync
  377.             status = DoCheckVsync( (ZVFlagRecord *) genericPtr );
  378.             break;
  379.         
  380.         case    cscZVGetInputFlags: // check for input capabilities
  381.             status = CheckInputCapabilities( (UInt32 *) genericPtr );
  382.             break;
  383.         
  384.         case    cscZVGetInfo: // get input HW capability
  385.             status = GetZVInfo( (ZVInfo *) genericPtr );
  386.             break;
  387.             
  388.         case    cscZVGetNumberOfInputs:
  389.             status = DoGetNumberOfInputs( (UInt16 *) genericPtr );
  390.             break;
  391.             
  392.         case    cscZVGetInput:
  393.             status = DoGetInput( (UInt16 *) genericPtr );
  394.             break;
  395.             
  396.         case    cscZVGetInputFormat:
  397.             status = DoGetInputFormat( (UInt16 *) genericPtr );
  398.             break;
  399.             
  400.         default:                    /* Unknown csCode        */
  401.             status = statusErr;
  402.             break;
  403.         }
  404.  
  405.     return status;
  406. }
  407.     
  408.  
  409. //=====================================================================================================
  410. //
  411. //  GetZoomVideo
  412. //
  413. //=====================================================================================================
  414. static OSStatus    GetZoomVideo( ZVFlagRecord *zvStatus)
  415. {
  416.     zvStatus->csFlag = gZVideoOn;
  417.     
  418.     return noErr;
  419. }
  420.  
  421. //=====================================================================================================
  422. //
  423. //  DoZoomVideo
  424. //
  425. //=====================================================================================================
  426. static OSStatus    DoZoomVideo( ZVFlagRecord *turnZVOn)
  427. {
  428.     OSStatus    status = noErr;
  429.  
  430.     //    do I/O write to port 01 to turn on ZV port
  431.     //    bit 0 is video control
  432.     //    bit 1 is audio control
  433.     //    (0x3 turns them both on)
  434.  
  435.     if (turnZVOn->csFlag)
  436.     {
  437.         // Do whatever is needed to enable ZoomVideo and set the status flag
  438.         gZVideoOn = true;
  439.         status = noErr;
  440.     }
  441.     else
  442.     {
  443.         // Do whatever is needed to disable ZoomVideo and set the status flag
  444.         gZVideoOn = false;
  445.         status = noErr;
  446.     }
  447.     
  448.     return status;
  449. }
  450.  
  451. //=====================================================================================================
  452. //
  453. //  CheckInputCapabilities
  454. //
  455. //  This routine is used by the on-board video digitizer to determine the capabilities of the ZV card.
  456. //  It mirrors the input capability flags described in Inside Macintosh: QuickTime Components, Chapter 8:  Video
  457. //  Digitizer Components, pages 8-14 through 8-15.
  458. //
  459. //=====================================================================================================
  460. static OSStatus CheckInputCapabilities(UInt32 * inputFlag)
  461. {
  462.         *inputFlag = (digiInDoesNTSC | digiInDoesComposite     | digiInDoesColor) ;
  463.         return noErr;
  464. }
  465.  
  466.  
  467. //=====================================================================================================
  468. //
  469. //  GetZVInfo
  470. //
  471. //  Returns information about the ZV card.  The different parameters are:
  472. //
  473. //  features:          Describes the different capabilities of the ZV Card
  474. //  isInterlaced:    Indicates whether the ZV data contains multiple fields.  0 = no, 1 = yes
  475. //  inputFormat:    Indicates what format the ZV data is in (composite, s-video, component)
  476. //  activeRect:        Indicates the coordinates for the video rectangle.
  477. //
  478. //=====================================================================================================
  479. static OSStatus    GetZVInfo(ZVInfo * zvInfo)
  480. {
  481.     OSStatus    status = noErr;
  482.     
  483.     // Set up the features that our card supports
  484.     zvInfo->features = kZVHasBrightness | kZVHasSaturation;
  485.     
  486.     // Report the current input flags. Note that since we only have one input and only
  487.     // support one standard, the currentFlags is not different from the ones reported in the
  488.     // CheckInputCapabilities.  If we were to support more than one standard, for example, then
  489.     // we would only report the current standard.
  490.     zvInfo->currentFlags = (digiInDoesNTSC | digiInDoesComposite | digiInDoesColor);
  491.     
  492.     // This is active/crop rectangle for our ZV card
  493.     zvInfo->activeRect.top = 0x001A;
  494.     zvInfo->activeRect.left = 0x0008;
  495.     zvInfo->activeRect.bottom = 0x01FA;
  496.     zvInfo->activeRect.right = 0x0288;
  497.  
  498.     // Our card always does interlace, so report it here
  499.     zvInfo->isInterlaced = true;
  500.     
  501.     return status;
  502. }
  503.  
  504.  
  505. //=====================================================================================================
  506. //
  507. // DoGetNumberOfInputs
  508. //
  509. // Returns the number of inputs supported by the ZV Card
  510. //
  511. //=====================================================================================================
  512. static OSStatus    DoGetNumberOfInputs( UInt16 *numberOfInputs )
  513. {
  514.     // We only support one input, so return that value here.  If we supported more than one, we would
  515.     // report that here:
  516.     *numberOfInputs = 1;
  517.     
  518.     return noErr;
  519. }
  520.  
  521.  
  522. //=====================================================================================================
  523. //
  524. // DoGetInput
  525. //
  526. // Returns the active input (zero-based).
  527. //
  528. //=====================================================================================================
  529. static OSStatus    DoGetInput( UInt16 *inputSource )
  530. {
  531.     // We only support one input, so we always say that source 0 is active.  If we supported more than one, we would
  532.     // report that here:
  533.     *inputSource = 0;
  534.     
  535.     return noErr;
  536. }
  537.  
  538.  
  539. //=====================================================================================================
  540. //
  541. // DoGetInputFormat
  542. //
  543. // Returns the format for the desired input source.
  544. //
  545. //=====================================================================================================
  546. static OSStatus    DoGetInputFormat( UInt16 *inputSource )
  547. {
  548.  
  549.     // We only support one format
  550.     
  551.     *inputSource = compositeIn;
  552.     
  553.     return noErr;
  554. }
  555.  
  556.  
  557. //=====================================================================================================
  558. //
  559. // DoGetAnalogDefaults
  560. //
  561. // Returns the default values for the supported analog settings.
  562. //
  563. //=====================================================================================================
  564. static OSStatus    DoGetAnalogDefaults( ZVAnalogControlRecord * myData)
  565. {
  566.     OSStatus                status = noErr;
  567.     UInt16                    defaultValue;
  568.  
  569.     // Look at the whichControl field and return the appropriate default
  570.     // value.  Note that we do not support kZVWhiteLevel or kZVBlackLevel, so
  571.     // we return a qtParamErr
  572.     
  573.     switch (myData->whichControl )
  574.     {
  575.         case kZVBrightness:
  576.             defaultValue = 0xa000;
  577.         break;
  578.         
  579.         case kZVSaturation:
  580.             defaultValue = 0x8500;
  581.         break;
  582.         
  583.         case kZVHue:
  584.             defaultValue = 0x8000;
  585.         break;
  586.  
  587.         case kZVContrast:
  588.             defaultValue = 0x8000;
  589.         break;
  590.         
  591.         case kZVSharpness:
  592.             defaultValue = 0x8000;
  593.         break;
  594.         
  595.         default:
  596.             status = qtParamErr;
  597.         break;
  598.     }
  599.  
  600.     // Return the default value
  601.     if ( status == noErr )
  602.         myData->value = defaultValue;
  603.     
  604.     return status;
  605. }
  606.  
  607. //=====================================================================================================
  608. //
  609. // DoAnalogControl
  610. //
  611. // Do the analog adjustment controls for SIO
  612. //
  613. //=====================================================================================================
  614. static OSStatus    DoAnalogControl( ZVAnalogControlRecord *analogData )
  615. {
  616.     OSStatus                status = noErr;
  617.     UInt8                    data;
  618.     UInt8                    result;
  619.     UInt16                    returnData;
  620.  
  621.     // The "value" parameter in the ZVAnalogControlRecord is a UInt16.  The actual value
  622.     // mirrors the corresponding parameter in the QuickTime VideoDigitizer section
  623.     data = ((analogData->value)>>12);
  624.     result = AdjustSIOData(data);
  625.     
  626.     switch (analogData->whichControl )
  627.     {
  628.         case kZVBrightness:
  629.             returnData = 0x1100 | result;
  630.             gBrightness = analogData->value;
  631.             break;
  632.         case kZVSaturation:
  633.             returnData = 0x1500 | result;
  634.             gSaturation = analogData->value;
  635.             break;
  636.         default:
  637.             returnData = 0x0000 | result;
  638.         break;
  639.     }
  640.  
  641.     // Send I2C here
  642.     WriteSIOLoop(returnData);
  643.     return status;
  644. }
  645.  
  646. //=====================================================================================================
  647. //
  648. //  DoCheckVsync
  649. //
  650. //  This routine will wait until a VSync signal is seen and will timeout after 18ms.  The status of 
  651. //  VSync signal is returned in the vsyncFlag parameter. 
  652. //
  653. //=====================================================================================================
  654. static OSStatus    DoCheckVsync( ZVFlagRecord * vSync)
  655. {
  656.     UInt8        timeOut = 18;
  657.     UInt8        value;
  658.     OSStatus    error = noErr;
  659.     
  660.     //
  661.     while (timeOut-- > 0) 
  662.     {
  663.         DelayForHardware(DurationToAbsolute(durationMillisecond * 1));        // wait 1 ms
  664.         value = gZVRegisters->zvInterrupt ;
  665.         if ( value & 0x02 ) 
  666.         {
  667.              vSync->csFlag = true;
  668.              break;
  669.          }
  670.     }
  671.     
  672.     vSync->csFlag = false;            
  673.     
  674.     return error;
  675. }
  676.  
  677. //=====================================================================================================
  678. //
  679. //  DoSetInputSource
  680. //
  681. //    This routine tells us to set the input source to be one of the zero-based inputs.
  682. //
  683. //=====================================================================================================
  684. static OSStatus    DoSetInputSource( UInt16 * inputNumber)
  685. {
  686.     OSStatus    error = noErr;
  687.     
  688.     // We only support one input, so the inputNumber has to be zero.
  689.     if ( *inputNumber != 0 )
  690.         error = qtParamErr;
  691.         
  692.     // If we actually supported more than one source, then we would do a range check and then
  693.     // hit the hardware to change to the specified source.
  694.     
  695.     return error;
  696. }
  697.  
  698. //=====================================================================================================
  699. //
  700. //  DoSetInputStandard
  701. //
  702. //    This routine tells us to set the input standard of the selected source..
  703. //
  704. //=====================================================================================================
  705. static OSStatus    DoSetInputStandard( UInt16 * inputStandard)
  706. {
  707.     OSStatus    error = noErr;
  708.     
  709.     // We only support NSTC, so if the parameter is not NTSC then report an error.
  710.     if ( *inputStandard != ntscIn )
  711.         error = qtParamErr;
  712.         
  713.     // If we actually supported more than one standard, then we would do a range check and then
  714.     // hit the hardware to change to the specified standard.
  715.     
  716.     return error;
  717. }
  718.  
  719.  
  720. #pragma mark -
  721. #pragma mark ••••• Utility Routines •••••
  722.  
  723. //=====================================================================================================
  724. //
  725. //  WriteSIOLoop
  726. //
  727. //  WriteSIO writes one byte of data into SIO register to adjust Brightness
  728. //
  729. //=====================================================================================================
  730. static OSStatus    WriteSIOLoop(UInt16    data)
  731. {
  732.     OSStatus    status = noErr;
  733.     UInt8        i,j;
  734.  
  735.         i = 0;
  736.         j = 0;
  737.         // Send the SIO command
  738.         while (i<4) {
  739.             if (CheckVsyn() == 1) {
  740.                 WriteSIO(data);
  741.                 i++;
  742.             }
  743.         }
  744.         // Send the termination command
  745.         while (j<2) {
  746.             if (CheckVsyn() == 1) {
  747.                 WriteSIO(0x0000);
  748.                 j++;
  749.             }
  750.         }
  751.         return status;
  752. }
  753.  
  754.  
  755. //=====================================================================================================
  756. //
  757. //  WriteSIOLoop
  758. //
  759. //=====================================================================================================
  760. static void    WriteSIO(UInt16    byte)
  761. {
  762.     OSStatus    status = noErr;
  763.     UInt8        data,cmd;
  764.  
  765.     data =  (byte & 0xFF) ;
  766.     cmd = byte >> 8;
  767.     SIOStart(true);
  768.     SIOSendByte( cmd );
  769.     SIOSendByte ( data );
  770.     SIOSendByte ( 0x00 );
  771.     SIOSendByte ( 0x00 );
  772.     SIOSendByte ( 0x00 );
  773.     SIOSendByte ( 0x00 );
  774.     SIOSendByte ( 0x00 );
  775.     SIOSendByte ( 0x00 );
  776.     SIOStart(false);
  777. }
  778. //=====================================================================================================
  779. //
  780. // SIOSendByte
  781. //
  782. //=====================================================================================================
  783. static void    SIOSendByte(UInt8 SIOdata)
  784. {
  785.     short    i;
  786.     
  787.     for (i=0;i<8;i++)
  788.     {
  789.         gvalue &= 0xF4;
  790.         gvalue |= ((SIOdata >> i) & 0x01);
  791.         SIORegWrite( gvalue);
  792.         gvalue |= 0x02;
  793.         SIORegWrite( gvalue);
  794.     }
  795. }
  796.  
  797. //=====================================================================================================
  798. //
  799. // SIOSendByte
  800. //
  801. //=====================================================================================================
  802. static void    SIORegWrite(UInt8 data)
  803. {
  804.     gZVRegisters->zvSIO = data;
  805.     DelayForHardware(DurationToAbsolute(durationMicrosecond * 25));        // wait 15 µs
  806. }
  807.  
  808.  
  809. //=====================================================================================================
  810. //
  811. // SIOStart
  812. //
  813. //=====================================================================================================
  814. static void    SIOStart(Boolean start)
  815. {
  816.     if (start) 
  817.     {
  818.         gvalue = gZVRegisters->zvSIO;
  819.         gvalue &= 0xF7;
  820.         gvalue |= 0x02;
  821.         gZVRegisters->zvSIO = gvalue;  // set CSK to 0
  822.         DelayForHardware(DurationToAbsolute(durationMicrosecond * 20));        // wait 15 µs
  823.     } 
  824.     else 
  825.     {
  826.         gvalue |= 0x08; // set CS to 1
  827.         SIORegWrite( gvalue);
  828.     }
  829. }
  830.  
  831. //=====================================================================================================
  832. //
  833. // AdjustSIOData
  834. //
  835. //=====================================================================================================
  836. static UInt8    AdjustSIOData(UInt8 data)
  837. {
  838.     data -= 3;
  839.     if (data > 6)
  840.         return (data - 7);
  841.     else if (data == 6)
  842.         return (0x00 );
  843.     else 
  844.         return (0x85 - data );
  845. }
  846.  
  847. //=====================================================================================================
  848. //
  849. // CheckVsyn
  850. //
  851. //=====================================================================================================
  852. static UInt16    CheckVsyn(void)
  853. {
  854.     UInt8        value,sync;
  855.     
  856.     // Vsync off check
  857.     do 
  858.     {
  859.         value = gZVRegisters->zvInterrupt ;
  860.     } while (!(value & 0x02));
  861.     
  862.     // Vsync on check
  863.     do 
  864.     {
  865.         value = gZVRegisters->zvInterrupt ;
  866.     } while ((value & 0x02) );
  867.     
  868.     sync = 1;
  869.     return sync;
  870. }
  871.  
  872.  
  873.  
  874.  
  875.  
  876.